我尝试两次编译以下代码,一次使用function hex2str($string) {
return preg_replace_callback(
'/(\\\\x[a-f\d]{2})+/i',
function ($matches) {
return stripcslashes($matches[0]);
},
$string
);
}
,一次不使用:
-m32
我的CMakeLists.txt中包含以下内容:
// File mylib.cc
#include <iostream>
void print_int_size() {
std::cout << sizeof(int*) << std::endl;
}
// File main.cc
void print_int_size();
int main() {
print_int_size();
return 0;
}
编译时会得到以下输出(类似于gcc):
project (Link32b VERSION 0.91 LANGUAGES CXX)
add_library ( mylib STATIC mylib.cc )
add_library ( mylib_32b STATIC mylib.cc )
target_compile_options ( mylib_32b PUBLIC -m32 )
add_executable ( main main.cc )
add_executable ( main_32b main.cc )
target_compile_options ( main_32b PRIVATE -m32 )
target_link_libraries ( main PRIVATE mylib )
target_link_libraries ( main_32b PRIVATE mylib_32b )
我在这里想念什么?
===
更新:很好奇,将Scanning dependencies of target mylib
[ 12%] Building CXX object CMakeFiles/mylib.dir/mylib.cc.o
[ 25%] Linking CXX static library libmylib.a
[ 25%] Built target mylib
Scanning dependencies of target main
[ 37%] Building CXX object CMakeFiles/main.dir/main.cc.o
[ 50%] Linking CXX executable main
[ 50%] Built target main
Scanning dependencies of target mylib_32b
[ 62%] Building CXX object CMakeFiles/mylib_32b.dir/mylib.cc.o
[ 75%] Linking CXX static library libmylib_32b.a
[ 75%] Built target mylib_32b
Scanning dependencies of target main_32b
[ 87%] Building CXX object CMakeFiles/main_32b.dir/main.cc.o
[100%] Linking CXX executable main_32b
ld: warning: ignoring file CMakeFiles/main_32b.dir/main.cc.o, file was built for i386 which is not the architecture being linked (x86_64): CMakeFiles/main_32b.dir/main.cc.o
ld: warning: ignoring file libmylib_32b.a, file was built for archive which is not the architecture being linked (x86_64): libmylib_32b.a
Undefined symbols for architecture x86_64:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [main_32b] Error 1
make[1]: *** [CMakeFiles/main_32b.dir/all] Error 2
make: *** [all] Error 2
设置为包含CMAKE_CXX_FLAGS
可以使示例工作。但是,我希望在不设置变量的情况下完成此操作,即遵循基于现代目标的方法。
答案 0 :(得分:0)
为简化项目的维护,建议您使构建系统尽可能简单,而应配置和构建项目 两次:
一个用于32位二进制文件的版本:
CXXFLAGS
和CFLAGS
环境变量设置为-m32
(方法1)AS
,CXX
和CC
(方法2)还请确保添加cmake_minimum_required
,否则将收到错误VERSION not allowed unless CMP0048 is set to NEW
。
cmake_minimum_required(VERSION 3.10)
project (Link VERSION 0.91 LANGUAGES CXX)
add_library ( mylib STATIC mylib.cc )
add_executable ( main main.cc )
target_link_libraries ( main PRIVATE mylib )
通过使用一个更简单的构建系统,该构建系统不对有关工具链的假设进行硬编码,因此可以隐式地启用对跨平台和不同环境(如ARM等)的支持,这也可以使持续集成变得更加容易。例如,在CircleCI上,您将有两个构建作业(一个用于64位,一个用于32位)均构建一个简单项目。
在Ubuntu上,可以这样做
sudo apt-get install \
gcc-multilib \
g++-multilib \
libc6:i386 \
libstdc++6:i386
其他依赖项将使用packageName:i386
假设我们具有以下目录结构:
<root>
|
|-src
| |--- CMakeLists.txt
| |--- main.cc
| |--- mylib.cc
|
|-build
| |-- ...
|
|-build-32
|-- ...
您只需执行以下操作即可编译32位版本:
CFLAGS=-m32 CXXFLAGS=-m32 cmake -Hsrc -Bbuild-32
方法2的目标是引入交叉编译的思想。
在上一节中,您将了解内部应用相同原理的dockcross/linux-32
码头工人镜像。
as
,gcc
和g++
创建三个包装器脚本以下是三个shell脚本的内容:
#!/bin/bash
exec as -m32 "$@"
#!/bin/bash
exec gcc -m32 "$@"
#!/bin/bash
exec g++ -m32 "$@"
假设我们具有以下目录结构:
<root>
|-bin
| |- i686-linux-gnu-as
| |- i686-linux-gnu-g++
| |- i686-linux-gnu-gcc
|
|-src
| |--- CMakeLists.txt
| |--- main.cc
| |--- mylib.cc
|
|-build
| |-- ...
|
|-build-32
|-- ...
您将分别做
64位$ cmake -Hsrc -Bbuild; cmake --build ./build
-- The CXX compiler identification is GNU 5.2.1
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/scratch/build
[...]
[100%] Built target main
$ file ./build/main
./build/main: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=e28e610f85cd4a2ab29e38ed58c1cb928f4aaf33, not stripped
$ ./build/main
4
32位
$ CXX=$(pwd)/bin/i686-linux-gnu-g++ \
CC=$(pwd)/bin/i686-linux-gnu-gcc \
AS=$(pwd)/bin/i686-linux-gnu-as linux32 \
bash -c "cmake -Hsrc -Bbuild-32; cmake --build ./build-32/"
-- The CXX compiler identification is GNU 5.2.1
-- Check for working CXX compiler: /tmp/scratch/bin/i686-linux-gnu-g++
-- Check for working CXX compiler: /tmp/scratch/bin/i686-linux-gnu-g++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
[...]
[100%] Built target main
$ file ./build-32/main
./build-32/main: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=b7f5781f66a28e28d28eda2b798b671c1e89e22a, not stripped
$ ./build-32/main
4
现在要了解为什么sizeof(int)
在64位和32位版本上都相同,请考虑阅读C/C++: sizeof(short), sizeof(int), sizeof(long), sizeof(long long), etc... on a 32-bit machine versus on a 64-bit machine
现在,要轻松编译为32位,您还可以使用对接图像dockcross/linux-x86
。参见https://github.com/dockcross/dockcross#readme
docker pull dockcross/linux-x86
docker run -ti --rm dockcross/linux-x86 > dockcross-linux-x86
chmod u+x dockcross-linux-x86
然后进行编译,您将这样做:
dockcross-linux-x86 bash -c "cmake -Hsrc -Bbuild-32; cmake --build ./build-32/"
答案 1 :(得分:0)
出于链接目的,未“继承” -m32
标志:
target_compile_options ( <lib> PUBLIC -m32 )
target_link_libraries ( <target> PRIVATE <lib> ) // Does not link with `-m32`.
请注意,由于{{1}的<target>
是“继承” -m32
的编译选项,因此上述内容导致target_link_libraries
被PUBLIC
编译 }}。但是,该标志 not 不会传递给链接器。
此外,没有<lib>
命令,因此无法插入行target_link_options
来解决问题。
相反,对于this answer(略有修改),正确的方法是
target_link_options ( <link> PUBLIC -m32 )
答案 2 :(得分:0)
OP's answer的附加内容:Cmake 3.13+ has target_link_options
命令,因此您可以编写:
target_link_options(<target> PRIVATE "-m32")