Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,21 @@ jobs:
- run: cargo build
- run: ./target/debug/catapult generate --source-dir test_data/test_xcode_basic --build-dir build --generator Xcode --toolchain test_data/toolchain_xcode.toml
- run: ls -R build
- run: xcodebuild -project build/basic/basic.xcodeproj -configuration Debug -target basic.exe SYMROOT=$PWD/build/basic/DerivedData build
- run: >
xcodebuild
-project build/basic/basic.xcodeproj
-configuration Debug
-scheme basic.exe
-derivedDataPath "$PWD/build/basic/DerivedData"
build
- run: ls -R build
- run: ./build/basic/DerivedData/Debug/basic.exe
- run: xcodebuild -project build/basic/basic.xcodeproj -configuration Release -target basic.exe SYMROOT=$PWD/build/basic/DerivedData build
- run: ./build/basic/DerivedData/Build/Products/Debug/basic.exe
- run: >
xcodebuild
-project build/basic/basic.xcodeproj
-configuration Release
-scheme basic.exe
-derivedDataPath "$PWD/build/basic/DerivedData"
build
- run: ls -R build
- run: ./build/basic/DerivedData/Release/basic.exe
- run: ./build/basic/DerivedData/Build/Products/Release/basic.exe
72 changes: 59 additions & 13 deletions src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ pub enum Generator {
Xcode,
}

enum Os {
Darwin,
Linux,
Windows,
}

impl Generator {
pub fn generate(
&self,
Expand All @@ -38,19 +44,8 @@ impl Generator {
} else {
String::new()
};
let target_platform = if target_triple.contains("-windows-") || target_triple.ends_with("-windows") {
TargetPlatform {
obj_ext: ".obj".to_owned(),
static_lib_ext: ".lib".to_owned(),
exe_ext: ".exe".to_owned(),
}
} else {
TargetPlatform {
obj_ext: ".o".to_owned(),
static_lib_ext: ".a".to_owned(),
exe_ext: "".to_owned(),
}
};
log::info!("target_triple: {}", target_triple);
let target_platform = TargetPlatform::from_target_triple(&target_triple);
ninja::Ninja::generate(project, build_dir, toolchain, profile, global_opts, target_platform)
}
Generator::Xcode => xcode::Xcode::generate(project, build_dir, toolchain, global_opts),
Expand All @@ -59,7 +54,58 @@ impl Generator {
}

pub struct TargetPlatform {
os: Os,
pub obj_ext: String,
pub static_lib_ext: String,
pub shared_lib_ext: String,
pub shared_link_ext: String,
pub exe_ext: String,
}

impl TargetPlatform {
pub fn from_target_triple(target_triple: &str) -> Self {
let target_platform = if target_triple.contains("-windows-") || target_triple.ends_with("-windows") {
TargetPlatform {
os: Os::Windows,
obj_ext: ".obj".to_owned(),
static_lib_ext: ".lib".to_owned(),
shared_lib_ext: ".dll".to_owned(),
shared_link_ext: ".lib".to_owned(),
exe_ext: ".exe".to_owned(),
}
} else if target_triple.contains("-darwin-") || target_triple.ends_with("-darwin") {
TargetPlatform {
os: Os::Darwin,
obj_ext: ".o".to_owned(),
static_lib_ext: ".a".to_owned(),
shared_lib_ext: ".dylib".to_owned(),
shared_link_ext: ".dylib".to_owned(),
exe_ext: "".to_owned(),
}
} else {
TargetPlatform {
os: Os::Linux,
obj_ext: ".o".to_owned(),
static_lib_ext: ".a".to_owned(),
shared_lib_ext: ".so".to_owned(),
shared_link_ext: ".so".to_owned(),
exe_ext: "".to_owned(),
}
};
target_platform
}
pub fn shared_runtime_identity_flags(&self, lib_name: &str) -> Option<String> {
match self.os {
Os::Darwin => Some(format!("-Wl,-install_name,@rpath/{lib_name}.dylib")),
Os::Linux => Some(format!("-Wl,-soname,{lib_name}.so")),
Os::Windows => None,
}
}

pub fn runtime_search_path_flags(&self, paths: &[String]) -> Vec<String> {
match self.os {
Os::Windows => Vec::new(),
Os::Darwin | Os::Linux => paths.iter().map(|path| format!("-Wl,-rpath,{path}")).collect(),
}
}
}
134 changes: 123 additions & 11 deletions src/generator/msvc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::{
misc::{Sources, index_map, join_parent},
object_library::ObjectLibrary,
project::{Project, ProjectInfo},
shared_library::SharedLibrary,
starlark_context::{StarContext, StarContextCompiler},
starlark_generator::eval_vars,
starlark_object_library::StarGeneratorVars,
Expand Down Expand Up @@ -120,6 +121,11 @@ struct ProfileFragment {
nasm_assemble_flags: Vec<String>,
}

struct DynamicImportSettings {
import_library: Option<String>,
ignore_import_library: Option<bool>,
}

fn item_definition_group(
platform: &str,
profile_name: &str,
Expand All @@ -128,6 +134,7 @@ fn item_definition_group(
include_dirs: &[String],
defines: &[String],
opts: &Options,
dynamic_import_settings: Option<&DynamicImportSettings>,
) -> Result<String, String> {
let mut ret = format!(
r#" <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='{profile_name}|{platform}'">
Expand All @@ -140,11 +147,26 @@ fn item_definition_group(
if !sources.nasm.is_empty() {
ret += &nasm_compile(profile, platform, include_dirs, defines)?;
}
if !profile.vcxproj.link.is_empty() {
let has_dynamic_import_settings = match dynamic_import_settings {
Some(settings) => settings.import_library.is_some() || settings.ignore_import_library.is_some(),
None => false,
};
if !profile.vcxproj.link.is_empty() || has_dynamic_import_settings {
ret += " <Link>\n";
for (key, val) in &profile.vcxproj.link {
ret += &format!(" <{key}>{val}</{key}>\n")
}
if let Some(import_settings) = dynamic_import_settings {
if let Some(import_library) = &import_settings.import_library {
ret += &format!(" <ImportLibrary>{import_library}</ImportLibrary>\n");
}
if let Some(ignore_import_library) = import_settings.ignore_import_library {
ret += &format!(
" <IgnoreImportLibrary>{}</IgnoreImportLibrary>\n",
if ignore_import_library { "true" } else { "false" }
);
}
}
ret += " </Link>\n";
}
ret += " </ItemDefinitionGroup>\n";
Expand All @@ -162,15 +184,33 @@ fn item_group_conditional(sources: &Sources, project_info: &ProjectInfo, platfor
ret += &item_group_tag;
for src in &sources.c {
let input = input_path(&src.full, &project_info.path);
ret += &format!(" <ClCompile Include=\"{input}\" />\n");
if src.full.ends_with(".c") {
ret += &format!(" <ClCompile Include=\"{input}\" />\n");
} else {
ret += &format!(
r#" <ClCompile Include="{input}">
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
"#
);
}
}
ret += " </ItemGroup>\n";
}
if !sources.cpp.is_empty() {
ret += &item_group_tag;
for src in &sources.cpp {
let input = input_path(&src.full, &project_info.path);
ret += &format!(" <ClCompile Include=\"{input}\" />\n");
if src.full.ends_with(".cpp") {
ret += &format!(" <ClCompile Include=\"{input}\" />\n");
} else {
ret += &format!(
r#" <ClCompile Include="{input}">
<CompileAs>CompileAsCpp</CompileAs>
</ClCompile>
"#
);
}
}
ret += " </ItemGroup>\n";
}
Expand Down Expand Up @@ -277,8 +317,9 @@ struct TargetData {
sources: Sources,
includes: Vec<String>,
defines: Vec<String>,
links: Vec<LinkPtr>,
direct_links: Vec<LinkPtr>,
generator_vars: Option<OwnedFrozenValue>,
output_name: Option<String>,
}

struct VcxprojOpts {
Expand Down Expand Up @@ -437,6 +478,11 @@ impl Msvc {
add_object_lib(lib, proj_opts, targets)?;
}
}
for lib in &project.shared_libraries {
if !targets.contains_key(&as_key(lib)) {
add_shared_lib(lib, proj_opts, targets)?;
}
}
for exe in &project.executables {
let configuration_type = "Application";
let project_info = &exe.project().info;
Expand All @@ -450,8 +496,9 @@ impl Msvc {
.map(|x| x.to_string_lossy().trim_start_matches(r"\\?\").to_owned())
.collect::<Vec<String>>(),
defines: exe.internal_defines(),
links: exe.links.clone(),
direct_links: exe.links.clone(),
generator_vars: exe.generator_vars.clone(),
output_name: exe.output_name.clone(),
};
let vsproj = make_vcxproj(proj_opts, targets, configuration_type, project_info, &target_data)?;
targets.insert(as_key(exe), vsproj);
Expand All @@ -474,7 +521,7 @@ fn add_static_lib(
.map(|x| x.to_string_lossy().trim_start_matches(r"\\?\").to_owned())
.collect::<Vec<String>>();
let defines = lib.internal_defines();
let links = lib
let direct_links = lib
.link_private
.iter()
.cloned()
Expand All @@ -485,8 +532,9 @@ fn add_static_lib(
sources: lib.sources.clone(),
includes,
defines,
links,
direct_links,
generator_vars: lib.generator_vars.clone(),
output_name: lib.output_name.clone(),
};
let vsproj = make_vcxproj(proj_opts, targets, "StaticLibrary", project_info, &target_data)?;
targets.insert(as_key(lib), vsproj.clone());
Expand All @@ -507,7 +555,7 @@ fn add_object_lib<'a>(
.map(|x| x.to_string_lossy().trim_start_matches(r"\\?\").to_owned())
.collect::<Vec<String>>();
let defines = lib.internal_defines();
let links = lib
let direct_links = lib
.link_private
.iter()
.cloned()
Expand All @@ -518,14 +566,48 @@ fn add_object_lib<'a>(
sources: lib.sources.clone(),
includes,
defines,
links,
direct_links,
generator_vars: lib.generator_vars.clone(),
output_name: lib.output_name.clone(),
};
let vsproj = make_vcxproj(proj_opts, targets, "StaticLibrary", project_info, &target_data)?;
targets.insert(as_key(lib), vsproj.clone());
Ok(vsproj)
}

fn add_shared_lib(
lib: &Arc<SharedLibrary>,
proj_opts: &VcxprojOpts,
targets: &mut TargetProjects,
) -> Result<VsProject, String> {
log::debug!("add_shared_lib: {}", lib.name);
let project_info = &lib.project().info;
let includes = lib
.internal_includes()
.into_iter()
.map(|x| x.to_string_lossy().trim_start_matches(r"\\?\").to_owned())
.collect::<Vec<String>>();
let defines = lib.internal_defines();
let direct_links = lib
.link_private
.iter()
.cloned()
.chain(lib.link_public.iter().cloned())
.collect();
let target_data = TargetData {
name: lib.name.clone(),
sources: lib.sources.clone(),
includes,
defines,
direct_links,
generator_vars: lib.generator_vars.clone(),
output_name: lib.output_name.clone(),
};
let vsproj = make_vcxproj(proj_opts, targets, "DynamicLibrary", project_info, &target_data)?;
targets.insert(as_key(lib), vsproj.clone());
Ok(vsproj)
}

fn make_vcxproj(
proj_opts: &VcxprojOpts,
targets: &mut TargetProjects,
Expand Down Expand Up @@ -576,6 +658,9 @@ fn make_vcxproj(
<PlatformToolset>{PLATFORM_TOOLSET}</PlatformToolset>
"#
);
if let Some(out) = &target_data.output_name {
out_str += &format!(" <TargetName>{out}</TargetName>\n");
}
// <UseDebugLibraries>true</UseDebugLibraries>
// <CharacterSet>MultiByte</CharacterSet>
// <WholeProgramOptimization>true</WholeProgramOptimization>
Expand Down Expand Up @@ -624,6 +709,22 @@ fn make_vcxproj(
.chain(generator_vars.defines.clone())
.collect::<Vec<_>>();
for (profile_name, profile) in &proj_opts.profiles {
let dynamic_import_settings = if configuration_type != "DynamicLibrary" {
None
} else {
Some(DynamicImportSettings {
import_library: if !profile.vcxproj.link.contains_key("ImportLibrary") {
Some("$(OutDir)$(TargetName).lib".to_owned())
} else {
None
},
ignore_import_library: if !profile.vcxproj.link.contains_key("IgnoreImportLibrary") {
Some(false)
} else {
None
},
})
};
item_definition_groups.push(item_definition_group(
platform,
profile_name,
Expand All @@ -632,6 +733,7 @@ fn make_vcxproj(
&includes_gen,
&defines_gen,
&proj_opts.opts,
dynamic_import_settings.as_ref(),
)?);
}
item_groups.push(item_group_conditional(&generator_sources, project_info, platform));
Expand Down Expand Up @@ -694,9 +796,9 @@ fn make_vcxproj(
}

let mut dependencies = Vec::new();
if !target_data.links.is_empty() {
if !target_data.direct_links.is_empty() {
out_str += " <ItemGroup>\n";
out_str += &add_project_references(&target_data.links, proj_opts, targets, &mut dependencies)?;
out_str += &add_project_references(&target_data.direct_links, proj_opts, targets, &mut dependencies)?;
out_str += " </ItemGroup>\n";
}
out_str += r#" <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
Expand Down Expand Up @@ -780,6 +882,16 @@ fn add_project_references(
LinkPtr::Interface(_) => {
out_str += &add_project_references(&link.public_links(), proj_opts, targets, dependencies)?;
}
LinkPtr::Shared(shared_lib) => {
let proj_ref = match targets.get(&as_key(shared_lib)) {
Some(x) => x,
None => {
add_shared_lib(shared_lib, proj_opts, targets)?;
targets.get(&as_key(shared_lib)).unwrap()
}
};
add_dependency(proj_ref);
}
}
}
Ok(out_str)
Expand Down
Loading