乱码三千 – 分享实用IT技术

乱码三千 – 码出一个新世界


  • 首页

  • 归档

  • 搜索

使用xmake交叉编译生成各个平台可执行程序

发表于 2022-09-29

xmake介绍

xmake 是一个基于 Lua 的轻量级跨平台构建工具,使用 xmake.lua维护项目构建, 相当于是cmake的增强版, 其优点如下:

  • 简单易用
  • 能够像 Make/Ninja 那样可以直接编译项目
  • 可以像CMake/Meson 那样生成工程文件
  • 内置的包管理系统来帮助用户解决 C/C++依赖库的集成使用问题
  • 可以实现跟C/C++进行混合编译
  • 编译速度也是非常的快,可以跟Ninja持平
  • 简化了交叉编译

官方文档

GITHUB

环境准备

  • 编译宿主平台: MAC

  • 交叉编译目标平台: Linux, Windows, IOS, Android ….

  1. 下载xmake

    1
    bash <(curl -fsSL https://xmake.io/shget.text -k)
  2. 测试c代码准备 文件取名为main

    1
    2
    3
    4
    5
    6
    #include <stdio.h>
    int main(int argc, char** argv){
    printf("Hello World!\n");

    return 0;
    }
  1. 在源码目录下新建xmake.lua文件

    并加入以下配置

    1
    2
    3
    4
    5
    6
    7
    8
    add_rules("mode.debug", "mode.release")

    -- 编译项目名称
    target("main")
    -- 指定编译形式 可执行文件 还是静态库or动态库
    set_kind("binary")
    -- 指定需要参与编译的源码文件
    add_files("src/main/c/main.c")

编译前的环境准备好了,那接下来 咱们挨个来实现目标平台的可执行文件生成

生成phone平台程序

  1. 下载xcode

    直接应用市场下载

  2. 给xmake指定编译目标平台

    1
    xmake f -p iphoneos
  3. 编译程序

    1
    xmake build main

    编译成功后 可以在build目录中找到对应的可执行文件

    image-20220929172751417

生成Mac平台的程序

  1. 给xmake指定编译目标平台

    1
    xmake f -p macosx
  2. 编译程序

    1
    xmake build main

    编译成功后 可以在build目录中找到对应的可执行文件

    image-20220929173058827

  3. 执行程序

    由于编译宿主平台刚好是Mac 所以我们可以直接执行程序

    1
    xmake run main

    image-20220929173203142

生成Windows平台程序

  1. 下载mingw-w64

    1
    brew install mingw-w64
  2. 给xmake指定编译目标平台

    1
    xmake f -p mingw

    或者使用图形化界面配置

    1
    xmake f --menu

    img

    配置完后 我们查看xmake的配置显示当前平台为mingw:

    image-20220930102409815

  3. 编译程序

    1
    xmake build main

    编译成功后 我们可以在build目录下找到生成的exe可执行文件:image-20220930101946291

  4. 关于mingw内部编译器

    我们打印编译信息会发现mingw内部采用的是gcc编译工具

    image-20220930102723811

生成Android平台程序

  1. 下载NDK

    点击进入下载页面

  2. 给xmake指定编译目标平台

    1
    xmake f -p android --ndk=ndk路径

    此时我们查看xmake配置显示当前编译平台为android:

    image-20220930101224522

  3. 编译程序

    1
    xmake build main

    编译成功后 可以在编译目录查看到生成的可执行文件

    image-20220930101319392

xmake常用指令

  1. 重置配置

    1
    xmake f -c
  2. 指定交叉编译工具

    1
    2
    3
    xmake f --toolchain=clang
    或者
    xmake f --toolchain=gcc
  3. 查看当前工程信息和xmake信息

    1
    xmake show
  4. 编译过程中查看完整的编译选项

    1
    xmake -rv
  5. 查看当前配置

    1
    xmake config -v

    image-20220929181646806

  6. 卸载xmake

    1
    xmake update --uninstall

常见问题汇总

  1. 交叉编译报错 unknown platform for xcode!

    解决方案: 卸载xmake重装

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

C/C++交叉编译各个平台可执行程序

发表于 2022-09-29

前言

目前主流的平台有:

  • Windows
  • Mac
  • Linux
  • Android
  • IOS

当C/C++程序写好后 如何快速在当前平台编译出各个平台的可执行文件

现在比较成熟的方案有:

  • 利用docker容器编译
  • 利用cmake构建交叉编译环境

利用docker容器编译

基于GCC套件, 可实现对Android, Linux, Windows, Web平台的交叉编译, 详细介绍如下:

  • dockcross/base

    Base image for other toolchain images. From Debian Jessie with GCC, make, autotools, CMake, Ninja, Git, and Python.

  • dockcross/android-arm

    The Android NDK standalone toolchain for the arm architecture.

  • dockcross/android-arm64

    The Android NDK standalone toolchain for the arm64 architecture.

  • dockcross/linux-arm64

    Cross compiler for the 64-bit ARM platform on Linux, also known as AArch64.

  • dockcross/linux-armv5

    Linux armv5 cross compiler toolchain for legacy devices like the Parrot AR Drone.

  • dockcross/linux-armv5-musl

    Linux armv5 cross compiler toolchain using musl as base “libc”.

  • dockcross/linux-armv6

    Linux ARMv6 cross compiler toolchain for the Raspberry Pi, etc.

  • dockcross/linux-armv7

    Generic Linux armv7 cross compiler toolchain.

  • dockcross/linux-armv7a

    Toolchain configured for ARMv7-A used in Beaglebone Black single board PC with TI SoC AM3358 on board, Cortex-A8.

  • dockcross/linux-mipsel

    Linux mipsel cross compiler toolchain for little endian MIPS GNU systems.

  • dockcross/linux-mips

    Linux mips cross compiler toolchain for big endian 32-bit hard float MIPS GNU systems.

  • dockcross/linux-s390x

    Linux s390x cross compiler toolchain for S390X GNU systems.

  • dockcross/linux-ppc64le

    Linux PowerPC 64 little endian cross compiler toolchain for the POWER8, etc. Important: Due to Issue #430, automatic build of newer images has been disabled.

  • dockcross/linux-x64

    Linux x86_64 / amd64 compiler. Since the Docker image is natively x86_64, this is not actually a cross compiler.

  • dockcross/linux-x86

    Linux i686 cross compiler.

  • dockcross/manylinux2014-x64

    Docker manylinux2014 image for building Linux x86_64 / amd64 Python wheel packages. It includes Python 3.5, 3.6, 3.7, 3.8, and 3.9. Also has support for the dockcross script, and it has installations of CMake, Ninja, and scikit-build. For CMake, it sets MANYLINUX2014 to “TRUE” in the toolchain.

  • dockcross/manylinux2014-x86

    Docker manylinux2014 image for building Linux i686 Python wheel packages. It includes Python 3.5, 3.6, 3.7, 3.8, and 3.9. Also has support for the dockcross script, and it has installations of CMake, Ninja, and scikit-build. For CMake, it sets MANYLINUX2014 to “TRUE” in the toolchain.

  • dockcross/manylinux2014-aarch64

    Docker manylinux2014 image for building Linux aarch64 / arm64 Python wheel packages. It includes Python 3.5, 3.6, 3.7, 3.8, and 3.9. Also has support for the dockcross script, and it has installations of CMake, Ninja, and scikit-build. For CMake, it sets MANYLINUX2014 to “TRUE” in the toolchain.

  • dockcross/manylinux2010-x64

    Docker manylinux2010 image for building Linux x86_64 / amd64 Python wheel packages. It includes Python 2.7, 3.4, 3.5, 3.6, 3.7 and 3.8. Also has support for the dockcross script, and it has installations of CMake, Ninja, and scikit-build. For CMake, it sets MANYLINUX2010 to “TRUE” in the toolchain.

  • dockcross/manylinux2010-x86

    Docker manylinux2010 image for building Linux i686 Python wheel packages. It includes Python 2.7, 3.4, 3.5, 3.6, 3.7 and 3.8. Also has support for the dockcross script, and it has installations of CMake, Ninja, and scikit-build. For CMake, it sets MANYLINUX2010 to “TRUE” in the toolchain.

  • dockcross/manylinux1-x64

    Docker manylinux1 image for building Linux x86_64 / amd64 Python wheel packages. It includes Python 2.7, 3.4, 3.5, 3.6, 3.7 and 3.8. Also has support for the dockcross script, and it has installations of CMake, Ninja, and scikit-build. For CMake, it sets MANYLINUX1 to “TRUE” in the toolchain.

  • dockcross/manylinux1-x86

    Docker manylinux1 image for building Linux i686 Python wheel packages. It includes Python 2.7, 3.4, 3.5, 3.6, 3.7 and 3.8. Also has support for the dockcross script, and it has installations of CMake, Ninja, and [ scikit-build](http:// scikit-build.org/). For CMake, it sets MANYLINUX1 to “TRUE” in the toolchain.

  • dockcross/web-wasm

    The Emscripten WebAssembly/asm.js/JavaScript cross compiler.

  • dockcross/windows-static-x64

    64-bit Windows cross-compiler based on MXE/MinGW-w64 with win32 threads and static linking.

  • dockcross/windows-static-x64-posix

    64-bit Windows cross-compiler based on MXE/MinGW-w64 with posix threads and static linking.

  • dockcross/windows-static-x86

    32-bit Windows cross-compiler based on MXE/MinGW-w64 with win32 threads and static linking.

  • dockcross/windows-shared-x64

    64-bit Windows cross-compiler based on MXE/MinGW-w64 with win32 threads and dynamic linking.

  • dockcross/windows-shared-x64-posix

    64-bit Windows cross-compiler based on MXE/MinGW-w64 with posix threads and dynamic linking.

  • dockcross/windows-shared-x86

    32-bit Windows cross-compiler based on MXE/MinGW-w64 with win32 threads and dynamic linking.

具体使用可参见Github

使用cmake构建交叉编译环境

首先我们需要下载cmake构建工具

然后下载用于交叉编译的套件

以Mac平台为例, 如果我需要编译各个平台的可执行文件, 那么首先需要下载能在Mac平台运行的目标平台编译包, 比如:

  • android平台:下载 Mac平台可运行的NDK (基于clang)

  • ios平台: 下载iphoneos SDK, xcode自带 我们只需下载xcode即可 (基于clang)

  • windows平台:下载MinGW 或者 MXE/MinGW-w64 (基于GCC)

  • Linux平台:如 arm/x86-Linux-gnueabi套件(基于GCC)

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

C语言中静态库static和动态库shared的区别

发表于 2022-09-28

前言

在c/c++语言编译时 我们经常能碰到关于静态库(static)和动态库(shared)的链接

那它们有什么区别呢

静态库

静态库(static)是程序在编译期间进行链接的, 它会被打包进可执行程序当中

动态库

动态库(shared)也叫共享库, 它是在程序运行是进行链接的, 以独立的文件存在, 不会被打包进可执行程序中, 但是程序在执行时需要能找到这个库的具体位置, 否则程序可能出错

不同系统中动态库的文件类型

系统 动态库后缀 静态库后缀
Linux .so .a
Mac .dylib .a
Windows .dll .lib

两种库的优势和劣势

静态库

优势:

  • 将依赖的静态库直接打包进可执行文件中, 不用担心对方的机器找不到库导致无法运行
  • 由于直接嵌入到了执行程序中 因此运行速度较快

劣势:

  • 会导致可执行文件的体积过大
  • 如果多个程序使用了同一个静态库 一旦静态库出现bug, 那么与之相关的所有可执行程序都要进行重新编译

动态库

优势:

  • 能有效减少可执行程序的体积
  • 一旦库出现bug, 只需修复并重新编译库即可

劣势:

  • 需要将库放到指定路径下 供主程序调用 操作起来相对麻烦
  • 运行速度相对静态库会慢一些

总结

静态库和动态库, 没有孰优孰劣一说, 具体看实际的应用场景, 每种库都有它的用武之地

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

CURL工具使用问题汇总

发表于 2022-09-28

问题1

下载时提示SSL certificate problem:

1
2
3
4
5
6
curl: (60) SSL certificate problem: certificate has expired
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

原因:

这是证书认证缺失导致,可以在请求时关闭ssl证书认证

解决方案:

命令行中加上-k即可, 如:

1
curl -fsSL https://xmake.io/shget.text -k

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

cmake的使用以及语法

发表于 2022-09-28

前言

我们使用 Make 工具构建项目时,需要编写 Makefile,但不同的平台 Make工具是不一样的,比如Linux的GNU Make ,Windows 的 nmake,它们对 Makefile的规范也是不一样的,如果软件要跨平台,则需要针对每一种 Make工具写一份 Makefile,非常浪费时间

而且当软件比较庞大时,Makefile的编写也会变的复杂。

CMake 简介

CMake(Cross-Platform-Make)是一个开源、跨平台的软件构建工具,它使用与平台独立的配置文件来对软件编译过程进行控制,根据用户所需,生成 Makefile 或者IDE的project。

CMake 构建过程

  1. 编写CMake 配置文件CMakeLists.txt,一般放在项目的最顶层目录下

  2. 运行 cmake 命令,参数为 CMakeLists.txt 所在根路径,执行完成后得到 Makefile 文件。

  3. 使用make 命令进行编译。

    1
    2
    3
    mkdir -p build && cd build
    cmake ..
    make

cmake基本语法

  1. 指定最小版本

    如果使用的 CMake版本低于该版本,则会发出致命错误

    1
    cmake_minimum_required(VERSION 3.9)
  2. 设置工程名 可以同时指定工程版本和语言,CXX代表C++

    1
    project(sunflower VERSION 0.0.1 LANGUAGES C CXX)
  3. 单行注释

    1
    # 我是注释
  4. 多行注释

    1
    2
    3
    #[[我是多行注释
    我是多行注释
    ]]
  5. 设置 c/c++版本

    1
    2
    set(CMAKE_C_STANDARD 11)
    set(CMAKE_CXX_STANDARD 11)
  6. 设置编译选项

    1
    2
    set(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS} -g -w -O3")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -w -O3")
  7. 添加宏定义

    1
    add_definitions(-DSPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_INFO)
  8. 设置头文件搜索目录

    实现编译时的 [-I] 选项,设置后引用头文件不需要使用相对路径,直接引用文件名

    1
    2
    3
    4
    5
    include_directories(
    "${PROJECT_SOURCE_DIR}/include"
    "${PROJECT_SOURCE_DIR}/depends/json/"
    "${PROJECT_SOURCE_DIR}/depends/leveldb/include"
    )
  9. 设置库文件搜索目录

    实现编译时的[-L]选项,项目内部明确路径的库文件,可以通过该命令指定

    1
    2
    3
    4
    link_directories(
    "${PROJECT_SOURCE_DIR}/depends/json/lib"
    "${PROJECT_SOURCE_DIR}/depends/leveldb"
    )
  10. 查找指定库文件

    查找到指定的预编译库,并将它的路径存储在变量中。

    默认的搜索路径为 cmake 包含的系统库,因此如果是NDK的公共库只需要指定库的name 即可(不需path),类似的命令还有find_file()、find_path()、find_program()、find_package()

    1
    find_library(log-lib,log)
  11. 查找指定目录下源文件
    获取指定目录下源文件列表,保存到 DIR_SRCS 变量中,后续编译构建目标可执行文件

    注意这里不能递归获取子目录下的源文件

    1
    aux_source_directory(${PROJECT_SOURCE_DIR}/src DIR_SRCS)
  12. 添加子目录源文件
    使用命令 add_subdirectory 指明本项目包含一个子目录,这样子目录下的 CMakeLists.txt文件和源文件也会被处理。

    项目包含多个子目录时,通常可以在子目录下也定义CMakeLists.txt 文件,并通过 add_library 生成包含子目录源码的库文件,并最终链接到目标可执行文件

    1
    2
    add_subdirectory(utils)
    add_subdirectory(config)
  13. 递归查找目录下的所有源文件
    可以通过 file命令递归获取指定目录下的所有源文件,这样可以不用为子目录专门定义CMakeLists.txt,也不需要通过链接的方式集成各个子目录,而是统一编译构建

    1
    2
    3
    4
    5
    file(GLOB_RECURSE DIR_SRCS
    ${PROJECT_SOURCE_DIR}/src/*.c
    ${PROJECT_SOURCE_DIR}/src/*.cc
    ${PROJECT_SOURCE_DIR}/src/*.cpp
    )
  14. 设置可执行文件输出路径

    1
    set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
  15. 生成可执行文件

    1
    add_executable(${PROJECT_NAME} ${DIR_SRCS})
  16. 生成库文件

    1
    2
    add_library(${PROJECT_NAME} STATIC ${DIR_SRCS})
    add_library(${PROJECT_NAME} SHARED ${DIR_SRCS})
  17. 链接库文件

    1
    2
    3
    4
    5
    6
    7
    set(EXTRA_LIBS
    sasl2
    libleveldb.a
    )
    target_link_libraries(${PROJECT_NAME}
    ${EXTRA_LIBS}
    )

常用变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
PROJECT_SOURCE_DIR:工程的根目录

PROJECT_BINARY_DIR:运行cmake命令的目录,通常为${PROJECT_SOURCE_DIR}/build

PROJECT_NAME:返回通过 project 命令定义的项目名称

CMAKE_CURRENT_SOURCE_DIR:当前处理的 CMakeLists.txt 所在的路径

CMAKE_CURRENT_BINARY_DIR:target 编译目录

CMAKE_CURRENT_LIST_DIR:CMakeLists.txt 的完整路径

EXECUTABLE_OUTPUT_PATH:重新定义目标二进制可执行文件的存放位置

LIBRARY_OUTPUT_PATH:重新定义目标链接库文件的存放位置

自定义变量

使用SET, 比如:

1
2
3
4
5
6
7
8
set(BINARY_NAME "juce_jni")

add_library( ${BINARY_NAME}

SHARED

"../../../Source/Main.cpp"
)

支持 Debug 版本

  1. 设置不同版本的编译选项

    1
    2
    set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
    set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")
  2. cmake 时指定版本

    1
    2
    cmake .. -DCMAKE_BUILD_TYPE=Debug
    cmake .. -DCMAKE_BUILD_TYPE=Release

完整示例

工程结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
+-- CMakeTest
|
+-- CMakeList.txt
+-- src
|
+-- main.cc
+--- utils/
|
+--- utils.cc
+--- utils.h
+-- config/
|
+-- config.cc
+-- config.h
+-- libs
|
+-- libleveldb.a

CMakeList.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
cmake_minimum_required(VERSION 3.7.1)

project(CMakeTest VERSION 0.0.1 LANGUAGES C CXX)

set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 11)

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -w -O3")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -w -O3")

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

include_directories(
"utils"
"config"
)

link_directories(
""${PROJECT_SOURCE_DIR}/libs""
)

# 子目录的CMakeList.txt也可以定义到主配置中
# 将utils和config两个子目录的源文件打包成库test_share
aux_source_directory(${PROJECT_SOURCE_DIR}/src/utils SHARE_SRC_FILES)
aux_source_directory(${PROJECT_SOURCE_DIR}/src/config SHARE_SRC_FILES)
add_library(test_share STATIC ${SHARE_SRC_FILES} )

aux_source_directory(${PROJECT_SOURCE_DIR}/src DIR_SRCS)
add_executable(${PROJECT_NAME} ${DIR_SRCS})

# 也可以使用file命令递归获取目录下所有源文件
file(GLOB_RECURSE DIR_SRCS
${PROJECT_SOURCE_DIR}/src/*.c
${PROJECT_SOURCE_DIR}/src/*.cc
${PROJECT_SOURCE_DIR}/src/*.cpp
)
add_executable(${PROJECT_NAME} ${DIR_SRCS})

set(EXTRA_LIBS
ldl
pthread
libleveldb.a
)

target_link_libraries(${PROJECT_NAME}
test_share
${EXTRA_LIBS}

)

本文转载自: CSDN

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

VST音频插件的开发

发表于 2022-09-27

关于

JUCE是一个开源的跨平台 C++ 应用程序框架,适用于桌面和移动应用程序,包括VST、VST3、AU、AUv3、RTAS 和 AAX音频插件。

GITHUB地址

JUCE官网

开发前的准备工作

  1. 下载juce

    image-20220928095652701

    点击进入下载页面

  2. 解压启动Porjucer, 并创建新工程

    image-20220928095935785

    image-20220928101600349

  3. 使用本地IDE编辑插件源码

    Mac平台支持Xcode,windows平台支持visual studio

iPlug框架

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

使用Clang对lua源码进行交叉编译

发表于 2022-09-27

什么是交叉编译

在一个平台上编译生成其他平台可运行的程序, 我们称之为交叉编译

以c语言为例, 在Mac平台编译出来的程序只能在Mac平台运行, 将其拷贝到Windows平台则无法识别, 解决这个问题的办法就是将源代码移至Windows平台 然后重新编译一次 这种做法属于原始的常规编译

那能不能在Mac平台编译生成能在Windows平台运行的程序呢, 可以, 只要借助交叉编译工具即可实现, 而这种非常规编译手段也叫做交叉编译

关于交叉编译实操, 详见之前的文章《android设备上如何运行C语言原生程序》

针对C/C++语言目前主流的交叉编译有:

  • GCC: GNU旗下的一款编译工具
  • CLANG: 苹果主导编写的一款基于LLVM的编译工具
  • MSVC: 微软旗下的一款编译工具

为什么使用Clang

相较之下, Clang编译速度更快, 占用内存更小, 错误提示更加人性化

Clang常规使用

我们先以一个C语言小程序来示范clang的编译流程

  1. 编写c程序代码 文件名为main,c

    1
    2
    3
    4
    5
    6
    7
    #include <stdio.h>

    int main(int argc, char** argv){
    printf("Hello World!\n");

    return 0;
    }
  2. 编译程序源码为当前平台可执行文件

    1
    clang main.c -o main

    -o:指定输出执行文件路径和程序名称

  3. 编译时顺带打印编译日志

    添加一个-v即可

    1
    clang main.c -o main -v
  4. 编译生成预处理文件

    使用-E, 区分大小写

    1
    clang -E main.c -o main
  5. 编译生成汇编代码

    使用-s, 区分大小写

    1
    clang -S main.c -o main
  6. 编译生成obj文件

    使用-c, 区分大小写

    1
    clang -c main.c -o main

Clang交叉编译

  1. 指定cpu架构

    使用-arch, 比如我们要编译生成arm64位架构平台可执行的程序

    1
    clang  main.c -o main -arch arm64

    正常情况下 上述指令会执行失败, 那是因为clang默认会使用本平台的SDK进行链接编译, 而本平台的SDK如果不支持arm的话自然无法编译 目前大部分电脑用的cpu依然还是x86架构的

    既然如此 倘若我们需要编译能在iPhone上运行的程序, 那么就需要指定可以支持arm的SDK来进行编译, 比如iphoneOS_SDK

  2. 指定编译SDK

    在clang中, 通过来-isysroot指定编译SDK, 如下:

    1
    clang -isysroot  /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.5.sdk main.c -o main -arch arm64

    编译成功后 生成的可执行文件即可在苹果手机上运行

  3. 指定操作系统

    1
    clang  main.c -o main -target x86_64-apple-darwin-eabi

    这里使用-target同时指定cpu架构和操作系统,-target的参数一共分为四部分:

    • arch:cpu架构 比如arm,x86_64
    • vendor: 工具连提供厂商 比如pc, apple,nvidia,ibm,等
    • os: 操作系统 比如darwin,linux ,win32
    • abi:应用程序二进制接口, 描述了程序在目标平台的运行规则, 比如eabi, androidabi ,gnueabi等

    每部分用横杆隔开, 合起来就是arch-vendor-os-abi

示例

  1. Mac编译android平台程序

    这里我使用的是ndk包下的clang进行编译

    1
    ndk/21.0.6113669/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang --target=armv7-none-linux-androideabi16 --sysroot=/Users/songjian/Library/Android/sdk/ndk/21.0.6113669/toolchains/llvm/prebuilt/darwin-x86_64/sysroot main.c -o androidExc
  2. Mac编译iphone平台程序

    1
    clang -isysroot  /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.5.sdk main.c -o main -arch arm64

lua源码交叉编译

接下来 我们在Mac平台上编译生成android上可执行的lua程序

由于lua源码文件比较多, 手敲命令编译太过繁琐, 因此我这里使用gradle+cmake构建工具进行快速编译

其中build.gradle配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apply plugin: 'c'
apply plugin: 'com.android.application'

android {
compileSdkVersion 30
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
defaultConfig {
//需要限制最小库版本不能太低 不然有些c库可能缺失
minSdkVersion 21
targetSdkVersion 30

}

}

这里 我将所有lua源码放置在了lua目录当中

CMakeLists.txt配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 限定cmake最小版本号 当前使用的版本必须在这个之上
cmake_minimum_required(VERSION 3.10.2)

# 描述工程名称
project("cproject")

# 自定义变量 使用${变量名}进行引用
set(EXEC_LUA "lua")
set(EXEC_LUAC "luac")

#获取指定目录下源文件列表,保存到 `DIR_SRCS` 变量中
aux_source_directory(${PROJECT_SOURCE_DIR}/src/main/c/lua DIR_SRCS )

#lua有两个主程序 单独抽出来
set(LUA_MAIN ${PROJECT_SOURCE_DIR}/src/main/c/lua/lua.c)
set(LUAC_MAIN ${PROJECT_SOURCE_DIR}/src/main/c/lua/luac.c)


#排除文件
list(REMOVE_ITEM DIR_SRCS ${PROJECT_SOURCE_DIR}/src/main/c/lua2/luac.c)
list(REMOVE_ITEM DIR_SRCS ${PROJECT_SOURCE_DIR}/src/main/c/lua2/luac.c)


# 生成可执行文件
add_executable(${EXEC_LUA}
${DIR_SRCS} ${LUA_MAIN})

add_executable(${EXEC_LUAC}
${DIR_SRCS} ${LUAC_MAIN})

编译工程后我们在build目录可以查看到生成的程序:

image-20220929105030969

将其push到root过的android设备上即可正常运行

关于工程配置, 如有疑问 可参考文章《使用Android Studio进行C/C++的开发》

附加

  1. Mac平台上查看可执行文件的架构

    1
    file 程序名 或 lipo –info 程序名
  2. 如果你的电脑安装了xcode, 那么可以使用xcrun来查看sdk路径

    查看当前平台SDK路径:

    1
    xcrun --show-sdk-path

    查看iphone平台SDK路径:

    1
    xcrun --sdk iphoneos --show-sdk-path

    甚至可以用xcrun配合clang简化编译指令:

    1
    2
    3
    xcrun -sdk iphoneos clang -arch arm64 -o main main.c
    或者
    clang -isysroot `xcrun --sdk iphoneos --show-sdk-path` main.c -o main -arch arm64

    以及本机平台

    1
    clang -isysroot `xcrun --show-sdk-path` main.c -o main -arch x86_64
  3. 目前iphoneOS_SDK支持的cpu架构有

    1
    2
    3
    4
    arm64
    armv7s
    armv7
    armv6

    x86系列处理器暂不支持

总结

关于GCC和Clang的使用对比:

GCC 会针对每一个编译主机和目标架构提供一套完整的套件,包含了二进制、头文件和库等。所以通常使用起来比较简单

而Clang 是复用一套编译系统去负责多个目标的编译任务,通过 -target选项来区分, 各个平台对应的头文件和库需要自己单独准备 编译的时候将路径通过参数告知给Clang, 使用起来相对会麻烦一些

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

iOS逆向篇-Clang交叉编译

发表于 2022-09-27

本篇我们的目标是在IPHONE上运行ARM64,C语言,C++和OC程序!

  1. Clang
    对于iOS开发者来说,Clang编译器一点也不陌生,Clang是一个C语言、C++、Objective-C、C++语言的轻量级编译器。源代码发布于BSD协议下,是基于LLVM的,也是Xcode 第一的编译器。
  2. 交叉编译
    指在一个平台上生成另一个平台上的可执行代码。现在我们就在Mac上写代码,在iPhone上运行,想想都刺激!
  3. 设备环境
    使用的是Mac和越狱iOS13.2.2的iPhoneX

ARM64

  1. 新建一个hello.txt文本
  2. 把下面代码复制进去,保存退出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.extern _printf
.align 4

.text
.global _main

_main:

stp x29, x30, [sp,#-0x10]! ;保存 x29 和 x30 寄存器到栈,!用来控制基址变址寻址的最终新地址是否进行回写操作
mov x29, sp ;将 sp 寄存器放入 x29 寄存器
sub sp,sp,#0x20 ;分配栈空间

adr x0,msg ;第一个参数
bl _printf

add sp,sp,#0x20 ;释放栈空间
mov sp,x29 ;将 x29 给 sp
ldp x29,x30,[sp],0x10 ;出栈给 x29 和 x30

ret ;返回

msg:
.asciz "Hello,world!\n" ; data段有一个标号msg,代表字符串"Hello,world!\n"的首地址,类型为.asciz的字符串
  1. 改文本后缀,改为hello.asm文件
  2. 打开终端,使开始编译
1
2
3
4
5
6
7
8
9
1、查看sdk安装路径
$xcrun --sdk iphoneos --show-sdk-path

2、clang编译
clang -arch arm64 -isysroot "sdk" -o hello hello.asm

// "-arch arm64" 指定框架
// " -isysroot" 指定sdk
// "-o" 输出目标文件
  1. 签名,在iOS系统中运行程序需要代码签名,所以要增加一个签名步骤。
    a.新建ent.plist
    b.把下面代码复制进去,保存在hello.asm同一目录下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>platform-application</key>
<true/>
<key>com.apple.springboard.debugapplications</key>
<true/>
<key>run-unsigned-code</key>
<true/>
<key>get-task-allow</key>
<true/>
<key>task_for_pid-allow</key>
<true/>
</dict>
</plist>
12345678910111213141516
  1. 对hello文件进行签名
1
2
codesign -s - --entitlements ent.plist -f hello
1

在这里插入图片描述

  1. 把签名后的hello文件拷进iPhone的/usr/bin/目录下,好像很多目录下都可以的
1
2
scp hello root@192.168.0.170:/usr/bin
1

在这里插入图片描述)在这里插入图片描述

  1. 运行hello文件,完美!

在这里插入图片描述)在这里插入图片描述

———————-华丽的分割线————————

C语言

  1. 新建1.txt
  2. 复制代码保存,文件改为1.c
1
2
3
4
5
6
7
8
9
#include <stdio.h>

int main()
{
printf("C:Hello, World! \n");

return 0;
}
12345678
  1. 编译签名

在这里插入图片描述

  1. 拷贝到iPhone上,运行, 完美!

在这里插入图片描述)img

———————-华丽的分割线————————

OBJECT-C

  1. 新建2.txt
  2. 复制代码保存,文件改为2.m
1
2
3
4
5
6
7
8
9
10
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSLog(@"OC:Hello World!");
}
return 0;
}
123456789
  1. 编译签名
    oc的编译有点不一样,因为导入了foundation框架,在Clang编译的时候需要指定一下
1
2
clang -arch arm64 -framework Foundation -isysroot "sdk" 2.m -o 2
1

在这里插入图片描述

  1. 拷贝到iPhone上,运行, 完美!

在这里插入图片描述)img

———————-华丽的分割线————————

C++

  1. 新建3.txt
  2. 复制代码保存,文件改为3.cpp
1
2
3
4
5
6
7
8
#include <iostream>
using namespace std;
int main()
{
cout << "C++:Hello, world!" << endl;
return 0;
}
1234567
  1. 编译签名
    因为clang完美兼容g++,gcc,所以一些命令可以完美继承!
    在这里插入图片描述
  2. 拷贝到iPhone上,运行, 完美!

在这里插入图片描述)img
———————-华丽的分割线————————

好了,今天的代码就敲到这里了,更多Clang的用法可以去看看文档。
文档:http://clang.llvm.org/docs/UsersManual.html

本文转载自: CSDN

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

使用Gradle将lua源码构建编译成可执行文件

发表于 2022-09-26

前言

对于lua的构建 官方默认使用make工具, 常见的构建工具有:

  • Make:又指GNU Make, 是Linux系统下的通用构建工具, 延伸的构建工具还有nmake, dmake, cmake, xmake等等
  • Scons: 以python语言编写的一款跨平台构建工具 对标make 容易学习快速上手
  • Ant: 基于java的构建工具, 被认为是make工具的替代品, 早期eclipse采用的构建工具就是它
  • maven: 同样是基于java, 它不单单是构建工具 还是项目管理工具, 属于Ant进化版, 目前Idea平台中 java的构建基本用的就是它
  • Gradle: 基于Groovy的构建工具, 被认为是Ant和Maven的替代品, 目前Android编译使用的构建工具就是它

什么是构建工具

以java程序为例, 我们在写好代码后, 需要使用javac指令对源码进行编译, 然后使用java指令执行

这个过程叫做编译, 如果一两个文件还好, 代码文件一多, 手动敲指令进行编译是会死人的🤪, 于是乎自动化的构建工具出现了, 目的就是为了取代人工编译

构建工具的发展

早期的make–>java的ant–>后来的maven–>现在的gradle

每一代构建工具的诞生, 都是为了解决上一代工具存在的痛点

Gradle, 用过的都说好!!😆

对Lua源码进行构建编译

我这边直接使用Android Studio, 具体步骤如下:

  1. 首先 去lua官网下载源码, 这里我使用的是5.4的源码

    lua官网

    image-20220926170825041

  2. 然后 在Studio中新建一个空工程, 然后将lua源码拖进src目录中

    image-20220926163907555

  3. 紧接着 对build.gradle文件进行配置

    lua一共包含两个可执行文件, 一个是lua另一个是luac, 所以这两个执行文件我们需要分开构建, 具体的gradle配置如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    apply plugin: 'c'  //使用c构建模式


    model {

    components {
    //创建一个lua执行文件构建入口
    lua(NativeExecutableSpec) {
    sources {
    c {//指定源码位置以及需要包含和排除的问价
    source {
    srcDir "src/main/c/lua"
    include '*.c'
    exclude 'luac.c'
    }
    exportedHeaders {
    include 'lauxlib.h', 'lua.h', 'lua.hpp', 'luaconf.h', 'lualib.h'
    }
    }
    }

    }
    //创建一个luac执行文件构建入口
    luac(NativeExecutableSpec) {
    sources {
    c {
    source {
    srcDir "src/main/c/lua"
    include '*.c'
    exclude 'lua.c'
    }
    exportedHeaders {
    include 'lauxlib.h', 'lua.h', 'lua.hpp', 'luaconf.h', 'lualib.h'
    }
    }
    }
    }

    }

    }
  4. 最后 开始编译
    gradle刷新同步后, 我们在右侧gradle任务面板可以看到多出lua和luac相关的task, 此时我们执行build任务开始对lua源码进行编译:

    image-20220926164804018

    编译完成后, 我们可以在build文件中查看到生成的可执行文件:

    image-20220926165101437

    双击可正常运行:

    image-20220926165135047

    至此 我们的lua编译完毕

附加

  1. 如果你只想编译lua而不编译luac, 那么可以单独运行luaExecutable:

    image-20220926172451757

  1. 在gradle配置文件中的组件的名称可以自定义

    image-20220926172714010

关于编译工具

编译工具和构建工具是两个不同的东西:

  • C/C++/Object-C语言常用的编译工具有: GCC,Clang

  • Java语言的编译工具为Javac, 当然GCC也能编译java语言

  • Android的编译工具为aapt,so库的编译早期采用的是GCC, 现在是Clang

上面对于lua的编译, 由于我测试时使用的是Mac平台, 同时电脑还装了Xcode, 所以内部默认采用的编译器是clang

关于Clang和GCC的介绍, 可以参见之前的文章《xcode中三种编译器的区别》

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

Linux 系统下使用 systemd 控制 frps 及配置开机自启

发表于 2022-09-22

操作

这个示例将会演示在 Linux 系统下使用 systemd 控制 frps 及配置开机自启。

在 Linux 系统下,使用systemd 可以方便地控制 frp 服务端 frps 的启动和停止、配置后台运行和开启自启。

要使用 systemd 来控制 frps,需要先安装 systemd,然后在 /etc/systemd/system 目录下创建一个 frps.service 文件。

  1. 如Linux服务端上没有安装 systemd,可以使用 yum 或 apt 等命令安装 systemd。

    1
    2
    3
    4
    # yum
    yum install systemd
    # apt
    apt install systemd
  2. 使用文本编辑器,如 vim 创建并编辑 frps.service 文件。

    1
    $ vim /etc/systemd/system/frps.service

    写入内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    [Unit]
    # 服务名称,可自定义
    Description = frp server
    After = network.target syslog.target
    Wants = network.target

    [Service]
    Type = simple
    # 启动frps的命令,需修改为您的frps的安装路径
    ExecStart = /path/to/frps -c /path/to/frps.ini

    [Install]
    WantedBy = multi-user.target
  3. 使用 systemd 命令,管理 frps。

    1
    2
    3
    4
    5
    6
    7
    8
    # 启动frp
    systemctl start frps
    # 停止frp
    systemctl stop frps
    # 重启frp
    systemctl restart frps
    # 查看frp状态
    systemctl status frps
  4. 配置 frps 开机自启。

    1
    systemctl enable frps

本文转载自: gofrp文档

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

1…101112…50

乱码三千

android程序员一枚,擅长java,kotlin,python,金融投资,欢迎交流~

491 日志
143 标签
RSS
© 2025 乱码三千
本站总访问量次
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4
0%