Skip to content

Commit ab35136

Browse files
committed
Merge branch 'main' into dev/grendel/llvm-18
* main: Back to wide strings on Windows + magic encantations (#22) [ci] Use managed identity for API Scan (#21) Fix `as.exe` crash on Windows (#20) Partially revert 9d342d5 (#19)
2 parents c65a994 + f3a4212 commit ab35136

24 files changed

+898
-433
lines changed

build-tools/automation/azure-pipelines.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,10 @@ extends:
311311
jobs:
312312
- job: api_scan
313313
displayName: API Scan
314-
pool: $(MicroBuildPoolName)
314+
pool:
315+
name: Maui-1ESPT
316+
image: $(WindowsPoolImage1ESPT)
317+
os: windows
315318
timeoutInMinutes: 360
316319
workspace:
317320
clean: all
@@ -347,7 +350,7 @@ extends:
347350
isLargeApp: true
348351
toolVersion: Latest
349352
env:
350-
AzureServicesAuthConnectionString: runAs=App;AppId=$(ApiScanClientId);TenantId=$(ApiScanTenant);AppKey=$(ApiScanSecret)
353+
AzureServicesAuthConnectionString: runAs=App;AppId=$(ApiScanMAUI1ESPTManagedId)
351354

352355
- task: SdtReport@2
353356
displayName: Guardian Export - Security Report

package.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ function prepare()
107107
else
108108
cp -P -a "${artifacts_source_bin}/${b}" "${artifacts_dest_bin}/${dest_b}"
109109
fi
110+
chmod 755 "${artifacts_dest_bin}/${dest_b}"
110111

111112
if [ -n "${src_pdb}" -a -f "${artifacts_source_bin}/${src_pdb}" ]; then
112113
cp -P -a "${artifacts_source_bin}/${src_pdb}" "${artifacts_dest_bin}/${dest_pdb}"

src/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ else() # UNIX
144144
/guard:cf
145145
/Zi
146146
/W3
147+
/utf-8
147148
)
148149

149150
set(COMMON_LINKER_ARGS
@@ -213,6 +214,7 @@ add_link_options("$<$<COMPILE_LANGUAGE:CXX>:${XA_UTILS_CXX_LINKER_FLAGS}>")
213214
add_link_options("$<$<COMPILE_LANGUAGE:C>:${XA_UTILS_C_LINKER_FLAGS}>")
214215

215216
if(WIN32)
217+
add_compile_definitions(_UNICODE)
216218
include_directories(compat)
217219
endif()
218220

src/compat-include/getopt.h

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#ifndef __GETOPT_H__
2+
/**
3+
* DISCLAIMER
4+
* This file has no copyright assigned and is placed in the Public Domain.
5+
* This file is part of the mingw-w64 runtime package.
6+
*
7+
* The mingw-w64 runtime package and its code is distributed in the hope that it
8+
* will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR
9+
* IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to
10+
* warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11+
*/
12+
13+
#define __GETOPT_H__
14+
15+
/* All the headers include this file. */
16+
#include <crtdefs.h>
17+
18+
#ifdef __cplusplus
19+
extern "C" {
20+
#endif
21+
22+
extern int optind; /* index of first non-option in argv */
23+
extern int optopt; /* single option character, as parsed */
24+
extern int opterr; /* flag to enable built-in diagnostics... */
25+
/* (user may set to zero, to suppress) */
26+
27+
extern char *optarg; /* pointer to argument of current option */
28+
29+
extern int getopt(int nargc, char * const *nargv, const char *options);
30+
31+
#ifdef __cplusplus
32+
}
33+
#endif
34+
/*
35+
* POSIX requires the `getopt' API to be specified in `unistd.h';
36+
* thus, `unistd.h' includes this header. However, we do not want
37+
* to expose the `getopt_long' or `getopt_long_only' APIs, when
38+
* included in this manner. Thus, close the standard __GETOPT_H__
39+
* declarations block, and open an additional __GETOPT_LONG_H__
40+
* specific block, only when *not* __UNISTD_H_SOURCED__, in which
41+
* to declare the extended API.
42+
*/
43+
#endif /* !defined(__GETOPT_H__) */
44+
45+
#if !defined(__GETOPT_BSD_H__) && defined(_BSD_SOURCE)
46+
#define __GETOPT_BSD_H__
47+
/*
48+
* BSD adds the non-standard `optreset' feature, for reinitialisation
49+
* of `getopt' parsing. We support this feature, for applications which
50+
* proclaim their BSD heritage, before including this header; however,
51+
* to maintain portability, developers are advised to avoid it.
52+
*/
53+
# define optreset __mingw_optreset
54+
extern int optreset;
55+
#endif /* !defined(__GETOPT_BSD_H__) && defined(_BSD_SOURCE) */
56+
57+
#if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__)
58+
#define __GETOPT_LONG_H__
59+
60+
#ifdef __cplusplus
61+
extern "C" {
62+
#endif
63+
64+
struct option /* specification for a long form option... */
65+
{
66+
const char *name; /* option name, without leading hyphens */
67+
int has_arg; /* does it take an argument? */
68+
int *flag; /* where to save its status, or NULL */
69+
int val; /* its associated status value */
70+
};
71+
72+
enum /* permitted values for its `has_arg' field... */
73+
{
74+
no_argument = 0, /* option never takes an argument */
75+
required_argument, /* option always requires an argument */
76+
optional_argument /* option may take an argument */
77+
};
78+
79+
extern int getopt_long(int nargc, char * const *nargv, const char *options,
80+
const struct option *long_options, int *idx);
81+
extern int getopt_long_only(int nargc, char * const *nargv, const char *options,
82+
const struct option *long_options, int *idx);
83+
/*
84+
* Previous MinGW implementation had...
85+
*/
86+
#ifndef HAVE_DECL_GETOPT
87+
/*
88+
* ...for the long form API only; keep this for compatibility.
89+
*/
90+
# define HAVE_DECL_GETOPT 1
91+
#endif
92+
93+
#ifdef __cplusplus
94+
}
95+
#endif
96+
97+
#endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */

src/gas/CMakeLists.txt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
set(GAS_DRIVER_SOURCES
2+
command_line.cc
23
gas.cc
34
llvm_mc_runner.cc
45
llvm_mc_runner_arm32.cc
@@ -33,10 +34,13 @@ add_executable(
3334
${GAS_DRIVER_SOURCES}
3435
)
3536

36-
# SYSTEM disables warnings produced by cxxopts headers, which we can do nothing about
37-
target_include_directories(as SYSTEM PRIVATE ${CMAKE_SOURCE_DIR}/../external/cxxopts/include)
38-
3937
if(WIN32)
38+
target_include_directories(
39+
as
40+
PRIVATE
41+
../compat-include
42+
)
43+
4044
target_link_libraries(
4145
as
4246
shlwapi

src/gas/command_line.cc

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
#include <algorithm>
4+
#include <optional>
5+
#include <vector>
6+
7+
#include "command_line.hh"
8+
#include "platform.hh"
9+
10+
using namespace xamarin::android::gas;
11+
namespace ranges = std::ranges;
12+
13+
bool CommandLine::parse (std::span<const CommandLineOption> options, std::vector<platform::string> &args, OptionCallbackFn option_cb)
14+
{
15+
uint32_t positional_count = 0;
16+
bool next_arg_is_value = false;
17+
std::optional<CommandLineOption> last_opt;
18+
19+
for (size_t i = 1; i < args.size (); i++) {
20+
platform::string &option = args[i];
21+
if (option.empty ()) {
22+
continue;
23+
}
24+
25+
platform::string::const_iterator iter = option.cbegin ();
26+
while (iter != option.cend () && *iter == DASH) {
27+
iter++;
28+
}
29+
30+
if (next_arg_is_value) {
31+
// getopt takes the next argument verbatim, if separated from the option requiring a value by a space.
32+
// This is done regardless of whether or not the next argument is prefixed with `-` or is a known one.
33+
if (last_opt.has_value ()) {
34+
option_cb (last_opt.value (), option);
35+
} else {
36+
STDERR << "Option '" << option << "' requires an argument.";
37+
return false;
38+
}
39+
40+
next_arg_is_value = false;
41+
last_opt.reset ();
42+
continue;
43+
}
44+
45+
if (iter == option.cbegin ()) { // positional
46+
option_cb ({ positional_count++ }, { option });
47+
continue;
48+
}
49+
50+
platform::string::const_iterator name_start = iter;
51+
while (iter != option.cend () && *iter != EQUALS) {
52+
iter++;
53+
}
54+
55+
#if !defined (__APPLE__)
56+
platform::string_view option_name { name_start, iter };
57+
#else
58+
platform::string_view option_name (option.data () + (name_start - option.cbegin ()), iter - name_start);
59+
#endif
60+
platform::string_view option_value;
61+
62+
if (iter != option.cend ()) { // has a value
63+
iter++;
64+
#if !defined (__APPLE__)
65+
option_value = { iter, option.cend () };
66+
#else
67+
option_value = platform::string_view (option.data () + (iter - option.cbegin ()), option.cend () - iter);
68+
#endif
69+
}
70+
71+
auto matching_option = [this, &option_name] (CommandLineOption const& o) -> bool {
72+
if (o.name != option_name) {
73+
return false;
74+
}
75+
76+
return o.arch == TargetArchitecture::Any || o.arch == target_arch;
77+
};
78+
79+
#if !defined(__APPLE__)
80+
auto match = ranges::find_if (options, matching_option);
81+
#else
82+
// C++ standard library on mac CI doesn't have std::ranges::find_if
83+
auto match = std::find_if (options.begin (), options.end (), matching_option);
84+
#endif
85+
if (match == options.end ()) {
86+
STDERR << "Unrecognized option '" << option << Constants::newline;
87+
continue;
88+
}
89+
90+
CommandLineOption opt = *match;
91+
if (opt.argument == ArgumentValue::Required && option_value.empty ()) {
92+
next_arg_is_value = true;
93+
last_opt = opt;
94+
continue;
95+
}
96+
97+
option_cb (opt, platform::string {option_value});
98+
}
99+
100+
if (last_opt.has_value ()) {
101+
STDERR << "Option '" << last_opt.value().name << "' requires an argument." << std::endl;
102+
return false;
103+
}
104+
105+
return true;
106+
}

src/gas/command_line.hh

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
// SPDX-License-Identifier: MIT
2+
#if !defined (GAS_COMMAND_LINE_HH)
3+
#define GAS_COMMAND_LINE_HH
4+
5+
#include <array>
6+
#include <cstdint>
7+
#include <functional>
8+
#include <iostream>
9+
#include <span>
10+
#include <string>
11+
#include <variant>
12+
13+
#if defined(_WIN32)
14+
#include <windows.h>
15+
#endif
16+
17+
#include "constants.hh"
18+
#include "platform.hh"
19+
20+
namespace xamarin::android::gas
21+
{
22+
enum class ArgumentValue
23+
{
24+
Required,
25+
NotRequired,
26+
};
27+
28+
enum class OptionId : uint32_t
29+
{
30+
Ignore = 100,
31+
O,
32+
Warn,
33+
G,
34+
MFPU,
35+
Version,
36+
VersionExit,
37+
Help,
38+
};
39+
40+
struct CommandLineOption
41+
{
42+
platform::string_view name;
43+
OptionId id;
44+
ArgumentValue argument;
45+
TargetArchitecture arch;
46+
47+
constexpr CommandLineOption (platform::string_view const& _name, OptionId _id, ArgumentValue _argument, TargetArchitecture _arch)
48+
: name (_name),
49+
id (_id),
50+
argument (_argument),
51+
arch (_arch)
52+
{}
53+
54+
constexpr CommandLineOption (platform::string_view const& _name, OptionId _id, TargetArchitecture _arch)
55+
: CommandLineOption (_name, _id, ArgumentValue::NotRequired, _arch)
56+
{}
57+
58+
constexpr CommandLineOption (platform::string_view const& _name, OptionId _id, ArgumentValue _argument)
59+
: CommandLineOption (_name, _id, _argument, TargetArchitecture::Any)
60+
{}
61+
62+
constexpr CommandLineOption (platform::string_view const& _name, OptionId _id)
63+
: CommandLineOption (_name, _id, ArgumentValue::NotRequired, TargetArchitecture::Any)
64+
{}
65+
};
66+
67+
class CommandLine
68+
{
69+
#if !defined(_WIN32)
70+
static constexpr bool is_windows = false;
71+
#else
72+
static constexpr bool is_windows = true;
73+
#endif
74+
75+
public:
76+
#if !defined(_WIN32)
77+
using TArgType = char*;
78+
79+
private:
80+
static inline constexpr char DASH = PCHAR('-');
81+
static inline constexpr char EQUALS = PCHAR('=');
82+
#else
83+
using TArgType = LPWSTR;
84+
85+
private:
86+
static inline constexpr wchar_t DASH = PCHAR('-');
87+
static inline constexpr wchar_t EQUALS = PCHAR('=');
88+
#endif
89+
90+
public:
91+
using TOptionValue = std::variant<bool, platform::string>;
92+
using TCallbackOption = std::variant<uint32_t, const CommandLineOption>;
93+
using OptionCallbackFn = std::function<void(TCallbackOption option, TOptionValue val)>;
94+
95+
public:
96+
explicit CommandLine (TargetArchitecture _target_arch) noexcept
97+
: target_arch (_target_arch)
98+
{}
99+
100+
template<size_t NElem>
101+
bool parse (std::array<CommandLineOption, NElem> const& options, std::vector<platform::string> &args, OptionCallbackFn option_cb)
102+
{
103+
return parse (std::span (options.data(), options.size()), args, option_cb);
104+
}
105+
106+
private:
107+
bool parse (std::span<const CommandLineOption> options, std::vector<platform::string> &args, OptionCallbackFn option_cb);
108+
109+
private:
110+
TargetArchitecture target_arch;
111+
};
112+
}
113+
114+
#define CLISTR(_str_lit_) PSTR((_str_lit_))
115+
116+
#if defined (_WIN32)
117+
#define CLIPARAM(_str_lit_) std::wstring_view { L ## _str_lit_ }
118+
#else
119+
#define CLIPARAM(_str_lit_) std::string_view { _str_lit_ }
120+
#endif
121+
122+
#endif // ndef GAS_COMMAND_LINE_HH

0 commit comments

Comments
 (0)