Skip to content

Commit b3f2a1d

Browse files
authored
Merge pull request #1911 from levydsa/fix_cross_mac
Fix cross compilation and build for sandboxes enviroments
2 parents e40c431 + 3ad67a8 commit b3f2a1d

1 file changed

Lines changed: 75 additions & 62 deletions

File tree

libsql-ffi/build.rs

Lines changed: 75 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -57,47 +57,41 @@ fn main() {
5757
build_bundled(&out_dir, &out_path);
5858
}
5959

60-
#[cfg(target_os = "windows")]
61-
fn copy_with_cp(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
62-
fs::copy(src, dst)?; // do a regular file copy on Windows
60+
fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
61+
let dst = dst.as_ref();
62+
fs::create_dir_all(dst)?;
63+
for entry in fs::read_dir(src)? {
64+
let entry = entry?;
65+
let ty = entry.file_type()?;
66+
if ty.is_dir() {
67+
copy_dir_all(entry.path(), dst.join(entry.file_name()))?;
68+
} else {
69+
fs::copy(entry.path(), dst.join(entry.file_name()))?;
70+
}
71+
}
6372
Ok(())
6473
}
6574

66-
#[cfg(target_os = "linux")]
67-
fn copy_with_cp(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
75+
/// This ensures that in sandboxed environments, such as Nix, permissions from other sources don't
76+
/// propagate into OUT_DIR. If not present, when trying to rewrite a file, a `Permission denied`
77+
/// error will occur.
78+
fn copy_with_cp(from: impl AsRef<Path>, to: impl AsRef<Path>) -> io::Result<()> {
6879
let status = Command::new("cp")
6980
.arg("--no-preserve=mode,ownership")
7081
.arg("-R")
71-
.arg(src.as_ref().to_str().unwrap())
72-
.arg(dst.as_ref().to_str().unwrap())
82+
.arg(from.as_ref().to_str().unwrap())
83+
.arg(to.as_ref().to_str().unwrap())
7384
.status()?;
7485

75-
if !status.success() {
76-
Err(io::Error::new(
77-
io::ErrorKind::Other,
78-
"Failed to copy using cp",
79-
))
80-
} else {
81-
Ok(())
86+
if status.success() {
87+
return Ok(());
8288
}
83-
}
84-
85-
#[cfg(target_os = "macos")]
86-
fn copy_with_cp(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
87-
let status = Command::new("cp")
88-
.arg("-R")
89-
.arg(src.as_ref().to_str().unwrap())
90-
.arg(dst.as_ref().to_str().unwrap())
91-
.status()?;
9289

93-
if !status.success() {
94-
Err(io::Error::new(
95-
io::ErrorKind::Other,
96-
"Failed to copy using cp",
97-
))
98-
} else {
99-
Ok(())
100-
}
90+
return match fs::copy(from.as_ref(), to.as_ref()) {
91+
Err(err) if err.kind() == io::ErrorKind::InvalidInput => copy_dir_all(from, to),
92+
Ok(_) => Ok(()),
93+
Err(err) => Err(err),
94+
};
10195
}
10296

10397
fn make_amalgamation() {
@@ -114,17 +108,19 @@ fn make_amalgamation() {
114108
.env("CFLAGS", flags.join(" "))
115109
.output()
116110
.unwrap();
111+
117112
Command::new("make")
118113
.current_dir(SQLITE_DIR)
119114
.output()
120115
.unwrap();
121116

122-
std::fs::copy(
117+
copy_with_cp(
123118
(SQLITE_DIR.as_ref() as &Path).join("sqlite3.c"),
124119
(BUNDLED_DIR.as_ref() as &Path).join("src/sqlite3.c"),
125120
)
126121
.unwrap();
127-
std::fs::copy(
122+
123+
copy_with_cp(
128124
(SQLITE_DIR.as_ref() as &Path).join("sqlite3.h"),
129125
(BUNDLED_DIR.as_ref() as &Path).join("src/sqlite3.h"),
130126
)
@@ -195,7 +191,7 @@ pub fn build_bundled(out_dir: &str, out_path: &Path) {
195191
}
196192

197193
let dir = env!("CARGO_MANIFEST_DIR");
198-
std::fs::copy(format!("{dir}/{bindgen_rs_path}"), out_path).unwrap();
194+
copy_with_cp(format!("{dir}/{bindgen_rs_path}"), out_path).unwrap();
199195

200196
let mut cfg = cc::Build::new();
201197
cfg.flag("-std=c11")
@@ -267,9 +263,7 @@ pub fn build_bundled(out_dir: &str, out_path: &Path) {
267263

268264
cfg.files(sqlean_sources);
269265

270-
let sqlean = Path::new(BUNDLED_DIR)
271-
.join("src")
272-
.join("sqlite3-sqlean-generated.c");
266+
let sqlean = Path::new(&env::var("OUT_DIR").unwrap()).join("sqlite3-sqlean-generated.c");
273267
generate_sqlean(&enabled_extensions, &sqlean).unwrap();
274268
cfg.file(&sqlean);
275269

@@ -415,7 +409,7 @@ fn copy_multiple_ciphers(target: &str, out_dir: &str, out_path: &Path) {
415409
build_multiple_ciphers(target, out_path);
416410
}
417411

418-
std::fs::copy(dylib, format!("{out_dir}/libsqlite3mc.a")).unwrap();
412+
copy_with_cp(dylib, format!("{out_dir}/libsqlite3mc.a")).unwrap();
419413
println!("cargo:rustc-link-lib=static=sqlite3mc");
420414
println!("cargo:rustc-link-search={out_dir}");
421415
}
@@ -426,32 +420,31 @@ fn build_multiple_ciphers(target: &str, out_path: &Path) {
426420
} else {
427421
"bundled/bindings/bindgen.rs"
428422
};
423+
429424
if std::env::var("LIBSQL_DEV").is_ok() {
430425
let header = HeaderLocation::FromPath(format!("{BUNDLED_DIR}/src/sqlite3.h"));
431426
bindings::write_to_out_dir(header, bindgen_rs_path.as_ref());
432427
}
428+
433429
let dir = env!("CARGO_MANIFEST_DIR");
434-
std::fs::copy(format!("{dir}/{bindgen_rs_path}"), out_path).unwrap();
435-
436-
std::fs::copy(
437-
(BUNDLED_DIR.as_ref() as &Path)
438-
.join("src")
439-
.join("sqlite3.c"),
440-
(BUNDLED_DIR.as_ref() as &Path)
441-
.join("SQLite3MultipleCiphers")
442-
.join("src")
443-
.join("sqlite3.c"),
430+
copy_with_cp(format!("{dir}/{bindgen_rs_path}"), out_path).unwrap();
431+
432+
let out_dir = env::var("OUT_DIR").unwrap();
433+
434+
copy_with_cp(
435+
dbg!(format!("{BUNDLED_DIR}/SQLite3MultipleCiphers")),
436+
format!("{out_dir}/sqlite3mc"),
444437
)
445438
.unwrap();
446439

447-
let bundled_dir = env::current_dir()
448-
.unwrap()
449-
.join(BUNDLED_DIR)
450-
.join("SQLite3MultipleCiphers");
451-
let out_dir = env::var("OUT_DIR").unwrap();
440+
copy_with_cp(
441+
PathBuf::from(BUNDLED_DIR).join("src").join("sqlite3.c"),
442+
format!("{out_dir}/sqlite3mc/src/sqlite3.c"),
443+
)
444+
.unwrap();
445+
446+
let bundled_dir = format!("{out_dir}/sqlite3mc");
452447
let sqlite3mc_build_dir = env::current_dir().unwrap().join(out_dir).join("sqlite3mc");
453-
let _ = fs::remove_dir_all(sqlite3mc_build_dir.clone());
454-
fs::create_dir_all(sqlite3mc_build_dir.clone()).unwrap();
455448

456449
let mut cmake_opts: Vec<&str> = vec![];
457450

@@ -474,15 +467,35 @@ fn build_multiple_ciphers(target: &str, out_path: &Path) {
474467
.unwrap();
475468

476469
if let Some(ref cc) = cross_cc {
477-
if cc.contains("aarch64") && cc.contains("linux") {
478-
cmake_opts.push(&cmake_toolchain_opt);
479-
writeln!(toolchain_file, "set(CMAKE_SYSTEM_NAME \"Linux\")").unwrap();
480-
writeln!(toolchain_file, "set(CMAKE_SYSTEM_PROCESSOR \"arm64\")").unwrap();
481-
}
482-
}
483-
if let Some(cc) = cross_cc {
470+
let system_name = if cc.contains("linux") {
471+
"Linux"
472+
} else if cc.contains("darwin") {
473+
"Darwin"
474+
} else if cc.contains("w64") {
475+
"Windows"
476+
} else {
477+
panic!("Unsupported cross target {}", cc)
478+
};
479+
480+
let system_processor = if cc.contains("x86_64") {
481+
"x86_64"
482+
} else if cc.contains("aarch64") {
483+
"arm64"
484+
} else {
485+
panic!("Unsupported cross target {}", cc)
486+
};
487+
488+
cmake_opts.push(&cmake_toolchain_opt);
489+
writeln!(toolchain_file, "set(CMAKE_SYSTEM_NAME \"{}\")", system_name).unwrap();
490+
writeln!(
491+
toolchain_file,
492+
"set(CMAKE_SYSTEM_PROCESSOR \"{}\")",
493+
system_processor
494+
)
495+
.unwrap();
484496
writeln!(toolchain_file, "set(CMAKE_C_COMPILER {})", cc).unwrap();
485497
}
498+
486499
if let Some(cxx) = cross_cxx {
487500
writeln!(toolchain_file, "set(CMAKE_CXX_COMPILER {})", cxx).unwrap();
488501
}

0 commit comments

Comments
 (0)